package com.android.systemui.ios.views;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.os.Build;

import com.android.systemui.ios.R;

public class ShortcutSlideView extends View {

    private final int BG_COLOR;
    private final int SELECT_COLOR = 0xccfafafa;

    private final RectF mRectF = new RectF();
    private final RectF mProgressRectF = new RectF();

    private final Paint mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Paint mSelectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Paint mBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG);

    private final int[] mLevels = new int[5];
    private final Bitmap[] mIcons = new Bitmap[5];
    private OnShortcutSlideChangedListener mListener;

    private final Point mIconSize = new Point();
    private final Point mDownPoint = new Point();
    private int mIconPaddingBottom;

    private PageShortcutView mPagerView;
    private boolean isRemoveRunnable = false;
    private boolean isLongClickEnable = false;
    private boolean isLongClickTrigger = false;
    private boolean isClickAnimationEnable = true;

    private int mMax = 100;
    private int mMin = 0;
    private int mProgress = 50;
    private int mChangingProgress = 50;
    private int mMove = 0;
    private int mRadius;

    public ShortcutSlideView(Context context) {
        this(context, null, 0);
    }

    public ShortcutSlideView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ShortcutSlideView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ShortcutSlideView, defStyleAttr, 0);
        final int N = a.getIndexCount();
        for (int i = 0; i < N; i++) {
            int attr = a.getIndex(i);
            if (attr == R.styleable.ShortcutSlideView_icon_1) {
                mIcons[0] = ((BitmapDrawable) a.getDrawable(attr)).getBitmap();
            } else if (attr == R.styleable.ShortcutSlideView_level_1) {
                mLevels[0] = a.getInt(attr, 1);
            } else if (attr == R.styleable.ShortcutSlideView_icon_2) {
                mIcons[1] = ((BitmapDrawable) a.getDrawable(attr)).getBitmap();
            } else if (attr == R.styleable.ShortcutSlideView_level_2) {
                mLevels[1] = a.getInt(attr, 2);
            } else if (attr == R.styleable.ShortcutSlideView_icon_3) {
                mIcons[2] = ((BitmapDrawable) a.getDrawable(attr)).getBitmap();
            } else if (attr == R.styleable.ShortcutSlideView_level_3) {
                mLevels[2] = a.getInt(attr, 3);
            } else if (attr == R.styleable.ShortcutSlideView_icon_4) {
                mIcons[3] = ((BitmapDrawable) a.getDrawable(attr)).getBitmap();
            } else if (attr == R.styleable.ShortcutSlideView_level_4) {
                mLevels[3] = a.getInt(attr, 4);
            } else if (attr == R.styleable.ShortcutSlideView_icon_5) {
                mIcons[4] = ((BitmapDrawable) a.getDrawable(attr)).getBitmap();
            } else if (attr == R.styleable.ShortcutSlideView_level_5) {
                mLevels[4] = a.getInt(attr, 5);
            } else if (attr == R.styleable.ShortcutSlideView_max) {
                mMax = Math.max(a.getInt(attr, 1), 1);
            } else if (attr == R.styleable.ShortcutSlideView_min) {
                mMin = Math.max(a.getInt(attr, 1), 1);
            } else if (attr == R.styleable.ShortcutSlideView_progress) {
                mProgress = a.getInt(attr, 0);
            } else if (attr == R.styleable.ShortcutSlideView_icon_paddingBottom) {
                mIconPaddingBottom = a.getDimensionPixelSize(attr, 0);
            } else if (attr == R.styleable.ShortcutSlideView_radius) {
                mRadius = a.getDimensionPixelSize(attr, 0);
            }
        }

        Resources res = getResources();
        BG_COLOR = res.getColor(R.color.ip_shortcut_background_color);

        mBgPaint.setColor(BG_COLOR);
        mSelectPaint.setColor(SELECT_COLOR);

        if (mProgress > mMax) {
            mProgress = mMax;
        }
        if (mProgress < mMin) {
            mProgress = mMin;
        }
        if (mIcons[0] != null) {
            mIconSize.set(mIcons[0].getWidth(), mIcons[0].getHeight());
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mRectF.left = getPaddingLeft();
        mRectF.right = getWidth() - getPaddingRight();
        mRectF.top = getPaddingTop();
        mRectF.bottom = getHeight() - getPaddingBottom();

        mProgressRectF.set(mRectF);

        float stepHeight = mProgressRectF.height() / (mMax - mMin);
        if (stepHeight < 1) {
            mProgressRectF.top = mProgressRectF.bottom - mProgressRectF.bottom * mProgress / (mMax - mMin);
            mProgressRectF.top -= mMove;
            if (mProgressRectF.top < mRectF.top) {
                mProgressRectF.top = mRectF.top;
            } else if (mProgressRectF.top >= mProgressRectF.bottom) {
                mProgressRectF.top = mProgressRectF.bottom;
            }
            mChangingProgress = (int) ((mProgressRectF.bottom - mProgressRectF.top) * (mMax - mMin) / (mRectF.height()));
        } else {
            int moveStep = (int) (mMove / stepHeight);
            mProgressRectF.top = mProgressRectF.bottom - (mProgress + moveStep) * stepHeight;
            mChangingProgress = Math.min(mProgress + moveStep, mMax);
            if (mChangingProgress >= mMax) {
                mProgressRectF.top = mRectF.top;
            } else if (mChangingProgress <= mMin) {
                mProgressRectF.top = mProgressRectF.bottom;
            }
        }
        mChangingProgress = Math.max(Math.min(mChangingProgress, mMax), mMin);

        canvas.drawRoundRect(mRectF, mRadius, mRadius, mBgPaint);
        int i = 4;
        int x = (int) (mRectF.left + (mRectF.width() - mIconSize.x) / 2);
        int y = (int) (mRectF.top + mRectF.height() - mIconSize.y) - mIconPaddingBottom;
        if (mChangingProgress < mLevels[0]) {
            i = 0;
        } else if (mChangingProgress < mLevels[1]) {
            i = 1;
        } else if (mChangingProgress < mLevels[2]) {
            i = 2;
        } else if (mChangingProgress < mLevels[3]) {
            i = 3;
        }

        if (mIcons[i] != null) {
            canvas.drawBitmap(mIcons[i], x, y, mBitmapPaint);
        }

        canvas.clipRect(mProgressRectF);
        canvas.drawRoundRect(mRectF, mRadius, mRadius, mSelectPaint);
        //canvas.clipRect(mRectF, Region.Op.UNION);
        if (Build.VERSION.SDK_INT >= 26) {
            canvas.clipRect(mRectF);
        } else {
            canvas.clipRect(mRectF, Region.Op.REPLACE);
        }

        if (mIcons[i] != null) {
            canvas.drawBitmap(mIcons[i], x, y, mBitmapPaint);
        }
    }

    public void setClickAnimationEnable(boolean enable) {
        isClickAnimationEnable = enable;
    }

    public void setLongClickEnable(boolean enable) {
        isLongClickEnable = enable;
    }

    public void setPagerView(PageShortcutView view) {
        mPagerView = view;
    }

    private final Runnable mLongClickRunnable = new Runnable() {

        @Override
        public void run() {
            if (mPagerView != null) {
                mPagerView.openZoomIn();
                isLongClickTrigger = true;
                performHapticFeedback(0);
            }
        }
    };

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownPoint.set(x, y);
                if (isClickAnimationEnable) {
                    animate().scaleX(0.97f).scaleY(0.97f).withEndAction(() -> animate().scaleX(1.0f).scaleY(1.0f).start()).start();
                }
                if (isLongClickEnable) {
                    isRemoveRunnable = false;
                    isLongClickTrigger = false;
                    postDelayed(mLongClickRunnable, 500);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (!isLongClickTrigger) {
                    mMove = mDownPoint.y - y;
                    if (!isRemoveRunnable && Math.abs(mMove) > 5) {
                        isRemoveRunnable = true;
                        removeCallbacks(mLongClickRunnable);
                    }
                    if (Math.abs(mMove) >= 2) {
                        invalidate();
                        if (mListener != null) {
                            mListener.onChanged(mMax, mMin, mChangingProgress, true);
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (!isRemoveRunnable) {
                    isRemoveRunnable = true;
                    removeCallbacks(mLongClickRunnable);
                }
                mMove = 0;
                mProgress = mChangingProgress;
                if (mListener != null) {
                    mListener.onChanged(mMax, mMin, mChangingProgress, false);
                }
                break;
        }
        return true;
    }

    public void setMaxMin(int max, int min) {
        setMaxMin(max, min, false);
    }

    public void setMaxMin(int max, int min, boolean resetLevel) {
        mMax = max;
        mMin = min;
        if (resetLevel) {
            for (int i = 0; i < 5; i++) {
                mLevels[i] = min + ((i + 1) * (max - min)) / 10;
            }
        }
        invalidate();
    }

    public void setProgress(int progress) {
        mProgress = progress;
        invalidate();
    }

    public void setOnShortcutSlideChangedListener(OnShortcutSlideChangedListener listener) {
        mListener = listener;
    }

    public interface OnShortcutSlideChangedListener {

        void onChanged(int max, int min, int progress, boolean tracking);
    }
}
